
#include <boost/test/unit_test.hpp>

#include <JuegoLib/Process.h>
#include <JuegoLib/ProcessManager.h>

BOOST_AUTO_TEST_SUITE( Process_System_Tests )


struct TestProc : public Process
{
	int mUpds;
	int mDeltas;

	void OnUpdate(int delta)
	{
		BOOST_CHECK( IsInitialized() == true );
		BOOST_CHECK( IsFinished() == false );
		BOOST_CHECK( IsAttached() == true );

		mUpds++;
		mDeltas += delta;

		if(mDeltas > 50)
			Finish(true);
		else if(mDeltas == 50)
			Finish(false);
	}

	TestProc(int type) : Process(type), mUpds(0), mDeltas(0)
	{
		
	}
};

BOOST_AUTO_TEST_CASE( ProcessClass )
{
	Process::Ptr pr;

	BOOST_REQUIRE_NO_THROW ( pr.reset( new TestProc( 20 ) ) );

	Process * p = pr.get();

	Process::Ptr pr2(new TestProc(21));
	Process::Ptr pr3(new TestProc(21));

	BOOST_REQUIRE( p != 0 );

	BOOST_CHECK ( p->GetType() == 20 );

	BOOST_CHECK ( ! p->IsFinished() );
	BOOST_CHECK( ! p->IsAttached() );
	BOOST_CHECK( ! p->IsSuccessful() );

	p->AddNext(pr2, true);
	BOOST_CHECK(p->GetNextList(true).size() == 1 && p->GetNextList(false).size() == 0);

	p->AddNext(pr3, false);
	BOOST_CHECK(p->GetNextList(true).size() == 1 && p->GetNextList(false).size() == 1);

	ProcessList prl = p->GetNextList(false);
	BOOST_CHECK( *prl.begin() == pr3 );

	BOOST_CHECK( pr3->IsAttached() == false );

	p->Finish(true);
	BOOST_CHECK( p->IsFinished() );
	BOOST_CHECK( p->IsSuccessful() );
}

BOOST_AUTO_TEST_CASE( ProcessManagerClass )
{
	ProcessManager::Ptr pmgr;
	BOOST_REQUIRE_NO_THROW ( pmgr.reset( new ProcessManager() ) );
	ProcessManager * pm = pmgr.get(); 
	BOOST_REQUIRE ( pm != 0 );

	Process::Ptr pr1(new TestProc(20));
	Process::Ptr pr2(new TestProc(21));
	Process::Ptr dep1(new TestProc(22));
	Process::Ptr dep2(new TestProc(23));
	Process::Ptr dep3(new TestProc(24));

	pr1->AddNext(dep1, true);
	pr1->AddNext(dep2, true);
	pr1->AddNext(dep3, false);

	BOOST_CHECK(pr1->GetNextList(true).size() == 2);
	BOOST_CHECK(pr1->GetNextList(false).size() == 1);

	pm->Attach(pr1);
	pm->Attach(pr2);

	BOOST_CHECK(dep1->IsAttached() == false);

	BOOST_REQUIRE( pr1->IsInitialized() == false );

	pm->Update(10);

	BOOST_REQUIRE ( pr1->IsInitialized() );

	pm->Update(5);
	pm->Update(10, 21);
	
	BOOST_REQUIRE( dynamic_cast<TestProc&>(*pr1.get()).mUpds == 2 );
	BOOST_REQUIRE( dynamic_cast<TestProc&>(*pr1.get()).mDeltas == 15);

	BOOST_REQUIRE( dynamic_cast<TestProc&>(*pr2.get()).mUpds == 3 );
	BOOST_REQUIRE( dynamic_cast<TestProc&>(*pr2.get()).mDeltas == 25);

	pm->Update(25, 21);
	BOOST_REQUIRE( dynamic_cast<TestProc&>(*pr2.get()).mDeltas == 50);
	BOOST_CHECK( pr2->IsFinished() );
	BOOST_CHECK( !pr2->IsSuccessful() );

	pm->Update(50);
	BOOST_REQUIRE( pr1->IsFinished() && pr1->IsSuccessful() );

	BOOST_CHECK( dep1->IsAttached() == true );

	ProcessList plist = pm->GetProcessList();

	BOOST_CHECK( plist.size() == 3 );

	pm->Update(60);

	plist = pm->GetProcessList();
	BOOST_CHECK( plist.size() == 0 );
}





BOOST_AUTO_TEST_SUITE_END()